package com.jamal2362.apktool.util;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.storage.StorageManager;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import brut.util.OS;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import com.jamal2362.apktool.R;
import com.jamal2362.apktool.fragment.files.Refreshable;
import com.jamal2362.apktool.task.DecodeTask;
import com.jamal2362.apktool.task.DeleteFileTask;
import com.jamal2362.apktool.task.ImportFrameworkTask;
import com.jamal2362.apktool.task.SAITask;
import com.jamal2362.apktool.task.SignTask;
import com.jamal2362.apktool.task.SignUtil;
import com.jamal2362.apktool.task.UnApkmTask;
import com.jamal2362.apktool.task.UnzipTask;
import com.jamal2362.apktool.task.VerifyTask;
import com.jamal2362.apktool.task.ZipAlign;
import com.jamal2362.apktool.task.ZipTask;
import com.jamal2362.apktool.util.Settings;
import com.jamal2362.apktool.util.TextUtil;

public class FileUtils {
	public static void open(File file, View view, final Refreshable refresh) {
		String n = file.getName().toLowerCase();
		if (n.endsWith(".apks") || n.endsWith(".zip") || n.endsWith(".xapk"))
			openApks(file, view, refresh);
		else if (n.endsWith(".apk"))
			openApk(file, view, refresh);
		else if (n.endsWith(".apkm"))
			openApkm(file, view, refresh);
		else if (n.endsWith(".arsc"))
			openArsc(view.getContext(), file, refresh);
		else
			openFile(view.getContext(), file);
	}

	public static void openArsc(Context c, File f, Refreshable r) {
		// new ASTask(c, r).execute(f);
		openFile(c, f);
	}

	public static void file(final File file, final View view, final Refreshable refresh) {
		final String aname = parseFileName(file.getName())[0];
		final boolean accessFile = file.getParentFile().canWrite();
		Menu menu = PopupUtils.show(view, R.menu.file, new PopupUtils.Callback(){
				@Override
				public void call(final Context ctx, final int pos) {
					switch (pos) {
						case R.id.delete:
							if (refresh.isSelectionMode()) {
								delete(ctx, refresh.getSelectedFiles(), refresh);
							} else {
								delete(ctx, new File[]{file}, refresh);
							}
							break;

						case R.id.compress:
							if (refresh.isSelectionMode()) {
								final File[] fls = refresh.getSelectedFiles();
								final String extension = (refresh.isApks() && fls.length > 1 ? ".apks" : ".zip");
								zipFiles(ctx, refresh, fls, extension);
							} else {
								zipFiles(ctx, refresh, new File[]{file}, ".zip");
							}
							break;

						case R.id.rename:
							rename(ctx, refresh, file);
							break;

						case R.id.open_in:
							FileUtils.openFile(ctx, file);
							break;

						case R.id.open_in_editor:
							refresh.getFrag().edit(file);
							break;

						case R.id.copy_file:
						case R.id.cut_file:
							JSONArray array = new JSONArray();
							try {
								if (refresh.isSelectionMode()) {
									File[] files = refresh.getSelectedFiles();
									array.put(0, files[0].getParent());
									for (int i = 0; i < files.length; i++) {
										array.put(i + 1, files[i].getName());
									}
								} else {
									array.put(0, file.getParent());
									array.put(1, file.getName());
								}
							} catch (JSONException e) {
								TextUtil.st(ctx, ctx.getString(R.string.error));
								break;
							}
							Settings.sets(ctx, "copy_file_path", array.toString());
							Settings.setb(ctx, "cut_file_mode", (pos == R.id.cut_file));
							refresh.refresh();
							break;

						case R.id.copy_path:
							TextUtil.setClipboard(ctx, file.getAbsolutePath());
							break;

						case R.id.set_as_output_directory:
							Settings.setOutputDirectory(file.getAbsolutePath(), ctx);
							break;

						case R.id.select_file:
							refresh.setSelection(file.getAbsolutePath());
							break;

						case R.id.select_all:
							refresh.selectAll(false);
							break;

						case R.id.select_inv:
							refresh.selectAll(true);
							break;

						case R.id.decompile:
							MUtil.decode(ctx, refresh, refresh.getSelectedFiles(), ctx.getString(R.string.decompile));
							break;

						case R.id.antisplit:
							File[] apks = refresh.getSelectedFiles();
							File[] capks = new File[apks.length];
							File outDir;
							boolean allToOut = Settings.getb(ctx, "all_to_out_dir", false);
							if (!accessFile || allToOut) {
								String dir = Settings.output_directory;
								if (dir == null) {
									TextUtil.st(ctx, ctx.getString(R.string.output_directory_not_set));
									return;
								}
								outDir = new File(dir + "/.A_AntiSplit_" + System.currentTimeMillis());
							} else {
								outDir = new File(file.getParent() + "/.A_AntiSplit_" + System.currentTimeMillis());
							}
							if (!outDir.exists())
								outDir.mkdirs();
							for (int i = 0; i < apks.length; i++) {
								File tmp = new File(outDir, apks[i].getName());
								copyFiles(apks[i], tmp);
								capks[i] = tmp;
							}
							DecodeTask dt = new DecodeTask(ctx, refresh, null);
							dt.antiSplit(true);
							dt.execute(capks);
							break;

						case R.id.exhere:
							unzip(ctx, refresh, file, file.getParentFile());
							break;

						case R.id.extoname:
							File out = new File(file.getParent() + "/" + aname);
							if (!out.exists())
								out.mkdirs();
							unzip(ctx, refresh, file, out);
							break;

						case R.id.zipalign:
							new ZipAlign(ctx, refresh).execute(refresh.getSelectedFiles());
							break;

						case R.id.file_details:
							MUtil.preFileDetails(ctx, file);
							break;

						case R.id.installSplit:
						case R.id.installnsignSplit:
							if (Build.VERSION.SDK_INT < 21)
								break;
							LayoutInflater inflater = LayoutInflater.from(ctx);
							View view = inflater.inflate(R.layout.search_progress, null);
							TextView tview = view.findViewById(R.id.searchprogressTextView1);
							tview.setText(R.string.mplease_wait);
							final AlertDialog progress = new AlertDialog.Builder(ctx)
								.setView(view)
								.setCancelable(false)
								.create();
							progress.show();
							Runnable inCallback = new Runnable()
							{
								@Override
								public void run() {
									File finalTempDir;
									if (!accessFile) {
										String dir = Settings.output_directory;
										if (dir == null) {
											TextUtil.st(ctx, ctx.getString(R.string.output_directory_not_set));
											return;
										}
										finalTempDir = new File(dir + "/.A_TempSplit_" + System.currentTimeMillis());
									} else {
										finalTempDir = new File(file.getParent() + "/.A_TempSplit_" + System.currentTimeMillis());
									}
									//final File finalTempDir = finalTempDir;
									finalTempDir.mkdir();
									for (File f : refresh.getSelectedFiles()) {
										copyFiles(f, new File(finalTempDir, f.getName()));
									}
									final File[] apks = finalTempDir.listFiles(new FilenameFilter() {
											@Override
											public boolean accept(File file, String p2) {
												return p2.endsWith(".apk");
											}
										});
									if (apks == null || apks.length == 0) {
										TextUtil.st(ctx, ctx.getString(R.string.error));
										OS.rmdir(finalTempDir);
										refresh.refresh();
										return;
									}
									SignUtil.loadKey(ctx, new SignUtil.LoadKeyCallback(){
											@Override
											public void call(SignUtil signTool) {
												new SAITask(ctx, refresh, signTool, pos == R.id.installnsignSplit).execute(apks);
											}
										});
									progress.cancel();
								}
							};
							new Handler().postDelayed(inCallback, 100);
							break;
					}
				}
			});
		if (refresh.isSelectionMode()) {
			menu.findItem(R.id.copy_path).setVisible(false);
			menu.findItem(R.id.set_as_output_directory).setVisible(false);
			menu.findItem(R.id.rename).setVisible(false);
			menu.findItem(R.id.open_in).setVisible(false);
			menu.findItem(R.id.open_in_editor).setVisible(false);
			menu.findItem(R.id.exhere).setVisible(false);
			menu.findItem(R.id.extoname).setVisible(false);
			menu.findItem(R.id.file_details).setVisible(false);
			if (!refresh.isSelected(file.getAbsolutePath())) {
				menu.findItem(R.id.delete).setVisible(false);
				menu.findItem(R.id.copy_file).setVisible(false);
				menu.findItem(R.id.cut_file).setVisible(false);
				menu.findItem(R.id.compress).setVisible(false);
			} else {
				menu.findItem(R.id.delete).setVisible(accessFile);
				menu.findItem(R.id.cut_file).setVisible(accessFile);
				menu.findItem(R.id.compress).setVisible(accessFile);
			}
			if (refresh.isApks() && refresh.isSelected(file.getAbsolutePath())) {
				menu.findItem(R.id.decompile).setVisible(true);
				menu.findItem(R.id.antisplit).setVisible(true);
				menu.findItem(R.id.zipalign).setVisible(true);
				if (Build.VERSION.SDK_INT >= 21) {
					menu.findItem(R.id.installSplit).setVisible(true);
					menu.findItem(R.id.installnsignSplit).setVisible(true);
				}
			}
			return;
		}
		boolean isExtracted = (file.getName().endsWith(".apk") || file.getName().endsWith(".apks") || file.getName().endsWith(".zip") || file.getName().endsWith(".jar"));
		if (file.getName().endsWith(".jar")) {
			final Context ctx = view.getContext();
			MenuItem mi = menu.add(0, 1000, 0, ctx.getString(R.string.import_framework));
			mi.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
				{
					@Override
					public boolean onMenuItemClick(MenuItem m) {
						new ImportFrameworkTask(ctx).execute(file);
						return true;
					}
				});
		}
		if (file.getName().endsWith(".json")) {
			final Context ctx = view.getContext();
			MenuItem mi = menu.add(0, 1001, 0, ctx.getString(R.string.import_scheme));
			mi.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
				{
					@Override
					public boolean onMenuItemClick(MenuItem m) {
						Runnable run = new Runnable()
						{
							public void run() {
								EditorTheme et = new EditorTheme();
								et.importTheme(ctx, file);
							}
						};
						MUtil.createDialog(ctx, ctx.getString(R.string.import_scheme_confirm, file.getAbsolutePath()), run);
						return true;
					}
				});
		}
		menu.findItem(R.id.open_in).setVisible(!file.isDirectory());
		menu.findItem(R.id.open_in_editor).setVisible(!file.isDirectory());
		menu.findItem(R.id.select_inv).setVisible(refresh.isSelectionMode());
		menu.findItem(R.id.extoname).setTitle(view.getContext().getString(R.string.mextract_zip_to, aname));

		menu.findItem(R.id.delete).setVisible(accessFile);
		menu.findItem(R.id.compress).setVisible(accessFile);
		menu.findItem(R.id.rename).setVisible(accessFile);
		menu.findItem(R.id.cut_file).setVisible(accessFile);
		menu.findItem(R.id.set_as_output_directory).setVisible(accessFile && file.isDirectory());
		menu.findItem(R.id.exhere).setVisible(accessFile && isExtracted);
		menu.findItem(R.id.extoname).setVisible(accessFile && isExtracted);
	}

	private static void rename(final Context ctx, final Refreshable refresh, final File file) {
		final EditText editText = new EditText(ctx);
		editText.setSingleLine(true);
		editText.setText(file.getName());
		AlertDialog.Builder builder = new AlertDialog.Builder(ctx).
			setTitle(R.string.rename).
			setView(editText).
			setPositiveButton(R.string.ok, new DialogInterface.OnClickListener(){
				@Override
				public void onClick(DialogInterface p1, int p2) {
					File src = file;
					String name1 = src.getName();
					String name2 = editText.getText().toString();
					if (name1.equals(name2))
						return;
					File dst = new File(src.getParentFile(), name2);
					if (!src.renameTo(dst))
						TextUtil.st(ctx, ctx.getString(R.string.error));
					refresh.refresh();
				}
			}).
			setNegativeButton(R.string.cancel, null);
		final AlertDialog dialog = builder.create();
		dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
		dialog.setOnShowListener(new DialogInterface.OnShowListener() {
				@Override
				public void onShow(DialogInterface p1) {
					editText.requestFocus();
					int dot = file.getName().lastIndexOf(".");
					if (dot <= 0 || file.isDirectory()) {
						dot = file.getName().length();
					}
					editText.setSelection(0, dot);
				}
			});
		dialog.show();
	}

	private static void delete(final Context ctx, final File[] file, final Refreshable refresh) {
		String files = "";
		for (int i = 0; i < file.length; i++) {
			if (i > 0)
				files += ", ";
			files += file[i].getName();
		}
		new AlertDialog.Builder(ctx).
			setTitle(R.string.delete).
			setMessage(files).
			setPositiveButton(R.string.ok, new DialogInterface.OnClickListener(){
				@Override
				public void onClick(DialogInterface p1, int p2) {
					new DeleteFileTask(ctx, refresh).execute(file);
				}
			}).
			setNegativeButton(R.string.cancel, null).
			show();
	}

	private static void zipFiles(final Context ctx, final Refreshable refresh, final File[] file, String extension) {
		if (file == null || file.length == 0) {
			TextUtil.st(ctx, ctx.getString(R.string.error));
			return;
		}
		final String outPath = file[0].getParent();
		String name = (file.length > 1 ? file[0].getParentFile().getName() : parseFileName(file[0].getName())[0]);
		final EditText editText = new EditText(ctx);
		editText.setText(genName(ctx, outPath, name, extension, 0));
		AlertDialog.Builder builder = new AlertDialog.Builder(ctx).
			setTitle(R.string.rename).
			setView(editText).
			setPositiveButton(R.string.ok, new DialogInterface.OnClickListener(){
				@Override
				public void onClick(DialogInterface p1, int p2) {
					String[] name = parseFileName(TextUtil.replaceIllegal(editText.getText().toString()));
					new ZipTask(ctx, outPath + "/" + genName(ctx, outPath, name[0], "." + name[1], 0), refresh).execute(file);
				}
			}).
			setNegativeButton(R.string.cancel, null);
		final AlertDialog dialog = builder.create();
		dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
		dialog.setOnShowListener(new DialogInterface.OnShowListener() {
				@Override
				public void onShow(DialogInterface p1) {
					editText.requestFocus();
					int dot = editText.getText().toString().lastIndexOf(".");
					if (dot <= 0) {
						editText.selectAll();
					} else {
						editText.setSelection(0, dot);
					}
				}
			});
		dialog.show();
	}

	private static void openApk(final File file, View view, final Refreshable refresh) {
		PopupUtils.show(view, R.menu.apk, new PopupUtils.Callback(){
				@Override
				public void call(final Context ctx, int pos) {
					switch (pos) {
						case R.id.decompile:
							MUtil.decode(ctx, refresh, new File[]{file}, file.getName());
							break;

						case R.id.translate:
							translate(ctx, file);
							break;

						case R.id.sign:
							SignUtil.loadKey(ctx, new SignUtil.LoadKeyCallback(){
									@Override
									public void call(SignUtil signTool) {
										new SignTask(ctx, refresh, signTool).execute(file);
									}
								});
							break;

						case R.id.verify:
							new VerifyTask(ctx).execute(file);
							break;

						case R.id.install:
							preInstall(ctx, file);
							break;

						case R.id.app_details:
							MUtil.showAppDetails(ctx, file, null, null);
							break;

						case R.id.import_framework:
							new ImportFrameworkTask(ctx).execute(file);
							break;

						case R.id.quick_edit:
							quickEdit(ctx, file, refresh);
							break;

						case R.id.zipalign:
							new ZipAlign(ctx, refresh).execute(file);
							break;
					}
				}
			});
	}

	private static void openApks(final File file, View view, final Refreshable refresh) {
		final boolean accessFile = file.getParentFile().canWrite();
		if (file.getName().endsWith(".zip") && !accessFile) {
			FileUtils.openFile(view.getContext(), file);
			return;
		}
		final boolean lolly = (Build.VERSION.SDK_INT >= 21);
		final String aname = parseFileName(file.getName())[0];
		Menu menu = PopupUtils.show(view, R.menu.apks, new PopupUtils.Callback(){
				@Override
				public void call(final Context ctx, final int pos) {
					switch (pos) {
						case R.id.app_details:
							MUtil.showAppDetails(ctx, file, null, null);
							break;

						case R.id.installSplit:
						case R.id.installnsignSplit:
							if (!lolly)
								break;
							openApks(ctx, file, refresh, (pos == R.id.installSplit ? 1 : 2));
							break;

						case R.id.antisplit:
							openApks(ctx, file, refresh, 0);
							break;

						case R.id.exhere:
							unzip(ctx, refresh, file, file.getParentFile());
							break;

						case R.id.extoname:
							File out = new File(file.getParent() + "/" + aname);
							if (!out.exists())
								out.mkdirs();
							unzip(ctx, refresh, file, out);
							break;
					}
				}
			});
		boolean isApks = (file.getName().endsWith(".apks") || file.getName().endsWith(".xapk"));
		menu.findItem(R.id.app_details).setVisible(isApks);
		menu.findItem(R.id.installSplit).setVisible(lolly && isApks);
		menu.findItem(R.id.installnsignSplit).setVisible(lolly && isApks);
		menu.findItem(R.id.antisplit).setVisible(isApks);
		menu.findItem(R.id.exhere).setVisible(accessFile);
		menu.findItem(R.id.extoname).setVisible(accessFile);
		menu.findItem(R.id.extoname).setTitle(view.getContext().getString(R.string.mextract_zip_to, aname));
	}

	private static void openApkm(final File file, View view, final Refreshable refresh) {
		final Menu menu = PopupUtils.show(view, R.menu.apkm, new PopupUtils.Callback(){
				@Override
				public void call(final Context ctx, final int pos) {
					switch (pos) {
						case R.id.to_apks:
							new UnApkmTask(ctx, refresh).execute(file);
							break;
					}
				}
			});
	}

	public static void openApks(final Context ctx, final File file, final Refreshable refresh, final int mode) {
		openApks(ctx, file, file.getName(), refresh, mode, false);
	}

	public static void openApks(final Context ctx, final File file, final String title, final Refreshable refresh, final int mode, final boolean removeSource) {
		final boolean accessFile = file.getParentFile().canWrite();
		switch (mode) {
			case 1: // установить
			case 2: // подписать и установить
				File tempDir;
				if (!accessFile) {
					String dir = Settings.output_directory;
					if (dir == null) {
						TextUtil.st(ctx, ctx.getString(R.string.output_directory_not_set));
						return;
					}
					tempDir = new File(dir + "/.A_TempSplit_" + System.currentTimeMillis());
				} else {
					tempDir = new File(file.getParent() + "/.A_TempSplit_" + System.currentTimeMillis());
				}
				final File finalTempDir = tempDir;
				Runnable inCallback = new Runnable()
				{
					@Override
					public void run() {
						final File[] apks = finalTempDir.listFiles(new FilenameFilter() {
								@Override
								public boolean accept(File file, String p2) {
									return p2.endsWith(".apk");
								}
							});
						if (apks == null || apks.length == 0) {
							TextUtil.st(ctx, ctx.getString(R.string.error));
							OS.rmdir(finalTempDir);
							refresh.refresh();
							return;
						}
						SignUtil.loadKey(ctx, new SignUtil.LoadKeyCallback(){
								@Override
								public void call(SignUtil signTool) {
									new SAITask(ctx, refresh, signTool, (mode == 2)).execute(apks);
								}
							});
					}
				};
				// unzip(ctx, refresh, file, finalTempDir, ".apk", inCallback);
				try {
					openApksDialog(ctx, refresh, file, finalTempDir, title, (mode == 1 ? R.string.install : R.string.install_sign), inCallback);
				} catch (Exception e) {
					TextUtil.st(ctx, ctx.getString(R.string.failed_open, file.getName()));
					e.printStackTrace();
				}
				break;

			case 0: // антисплит
				File outDir;
				boolean allToOut = Settings.getb(ctx, "all_to_out_dir", false);
				if (!accessFile || allToOut || removeSource) {
					String dir = Settings.output_directory;
					if (dir == null) {
						TextUtil.st(ctx, ctx.getString(R.string.output_directory_not_set));
						return;
					}
					outDir = new File(dir + "/.A_AntiSplit_" + System.currentTimeMillis());
				} else {
					outDir = new File(file.getParent() + "/.A_AntiSplit_" + System.currentTimeMillis());
				}
				final File finalDir = outDir;
				Runnable callback = new Runnable()
				{
					@Override
					public void run() {
						if (removeSource)
							file.delete();
						File[] apks = finalDir.listFiles(new FilenameFilter() {
								@Override
								public boolean accept(File file, String p2) {
									return p2.endsWith(".apk");
								}
							});
						if (apks == null || apks.length == 0) {
							TextUtil.st(ctx, ctx.getString(R.string.error));
							OS.rmdir(finalDir);
							refresh.refresh();
							return;
						}
						DecodeTask dt = new DecodeTask(ctx, refresh, null);
						dt.antiSplit(true);
						dt.execute(apks);
					}
				};
				// unzip(ctx, refresh, file, finalDir, ".apk", callback);
				try {
					openApksDialog(ctx, refresh, file, finalDir, title, R.string.mantisplit, callback);
				} catch (Exception e) {
					TextUtil.st(ctx, ctx.getString(R.string.failed_open, file.getName()));
					e.printStackTrace();
				}
				break;
		}
	}

	private static void openApksDialog(final Context ctx, final Refreshable refresh, final File apks, final File extractDir, final String title, final int positive, final Runnable callback) throws Exception {
		final List<String> filesList = new ArrayList<String>();
		ZipFile zip = new ZipFile(apks);
        Enumeration e = zip.entries();
		int index = 0;
        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
			if (entry.getName().toLowerCase().endsWith(".apk") && !entry.getName().contains(File.separator)) {
				filesList.add(entry.getName());
				index++;
			}
		}
		if (filesList.isEmpty()) {
			TextUtil.st(ctx, ctx.getString(R.string.errorf, "apk files not found in " + apks.getAbsolutePath()));
			return;
		}
		AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
		builder.setMultiChoiceItems(filesList.toArray(new String[filesList.size()]), null, null);
		builder.setTitle(title);
		builder.setNegativeButton(R.string.cancel, null);
		builder.setPositiveButton(positive, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface p1, int p2) {
					List<String> files = new ArrayList<String>();
					ListView list = ((AlertDialog) p1).getListView();
					for (int i = 0; i < list.getCount(); i++) {
						if (list.isItemChecked(i)) {
							files.add((String) list.getItemAtPosition(i));
						}
					}
					if (files.isEmpty())
						return;
					if (!extractDir.exists())
						extractDir.mkdirs();
					new UnzipTask(ctx, refresh, extractDir, files, callback).execute(apks);
				}
			});
		builder.setNeutralButton(R.string.mselect_all, null);
		final AlertDialog dialog = builder.create();
		dialog.setOnShowListener(new DialogInterface.OnShowListener()
			{
				@Override
				public void onShow(DialogInterface p1) {
					final Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
					positiveButton.setEnabled(false);
					final ListView listView = dialog.getListView();
					listView.setOnItemClickListener(new OnItemClickListener() {  
							@Override  
							public void onItemClick(AdapterView<?> parent, View view, int position, long id) {    
								for (int i = 0; i < listView.getCount(); i++) {
									if (listView.isItemChecked(i)) {
										positiveButton.setEnabled(true);
										return;
									}
								}
								positiveButton.setEnabled(false);
							}  
						});  
					final Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
					neutralButton.setOnClickListener(new OnClickListener() {
							@Override
							public void onClick(View p1) {
								boolean checkedAll = false;
								for (int i = 0; i < listView.getCount(); i++) {
									if (!listView.isItemChecked(i)) {
										checkedAll = true;
										break;
									}
								}
								for (int i = 0; i < listView.getCount(); i++) {
									listView.setItemChecked(i, checkedAll);
								}
								positiveButton.setEnabled(checkedAll);
							}
						});
				}
			});
		dialog.show();
	}

	private static void translate(Context ctx, File file) {
		// TODO
	}

	public static void preInstall(final Context context, final File apk) {
		if (Settings.getb(context, "check_install", true)) {
			LayoutInflater inflater = LayoutInflater.from(context);
			View view = inflater.inflate(R.layout.search_progress, null);
			TextView tview = view.findViewById(R.id.searchprogressTextView1);
			tview.setText(R.string.mplease_wait);
			final AlertDialog progress = new AlertDialog.Builder(context)
				.setView(view)
				.setCancelable(false)
				.create();
			progress.show();
			Runnable checkApk = new Runnable()
			{
				@Override
				public void run() {
					final Apkinfo appInfo = new Apkinfo(context, apk);
					if (!appInfo.isValid()) {
						TextUtil.st(context, context.getString(R.string.mapk_damage));
						progress.cancel();
						return;
					}
					if (!isPackageInstalled(appInfo.pname(), appInfo.getPackageManager())) {
						installPKG(context, apk);
						progress.cancel();
						return;
					}
					HashSet<Integer> signatures = signaturesByPath(context, apk.getAbsolutePath());
					if (signatures.size() == 0) {
						TextUtil.st(context, context.getString(R.string.mapk_nosign));
						progress.cancel();
						return;
					}
					HashSet<Integer> signatures2 = signaturesByName(context, appInfo.pname());
					if (signatures.containsAll(signatures2)) {
						installPKG(context, apk);
						progress.cancel();
						return;
					}
					AlertDialog.Builder builder = new AlertDialog.Builder(context);
					builder.setMessage(R.string.mapk_sign_fail);
					builder.setNegativeButton(R.string.cancel, null);
					builder.setPositiveButton(R.string.install, new DialogInterface.OnClickListener()
						{
							@Override
							public void onClick(DialogInterface p1, int p2) {
								installPKG(context, apk);
							}
						});
					builder.setNeutralButton(R.string.mshow_more_options, null);
					final AlertDialog dialog = builder.create();
					dialog.setOnShowListener(new DialogInterface.OnShowListener()
						{
							@Override
							public void onShow(DialogInterface p1) {
								Button neutral = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
								neutral.setOnClickListener(new View.OnClickListener() {
										@Override
										public void onClick(View v) {
											PopupMenu menu = new PopupMenu(context, v);
											int mid = 1300;
											MenuItem verify = menu.getMenu().add(0, mid++, 0, context.getString(R.string.verify));
											verify.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
												{
													@Override
													public boolean onMenuItemClick(MenuItem m) {
														new VerifyTask(context).execute(apk);
														return true;
													}
												});
											MenuItem settings = menu.getMenu().add(0, mid++, 0, context.getString(R.string.settings));
											settings.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
												{
													@Override
													public boolean onMenuItemClick(MenuItem m) {
														MUtil.goToSettings(context, appInfo.pname());
														return true;
													}
												});
											MenuItem launch = menu.getMenu().add(0, mid++, 0, context.getString(R.string.launch_app));
											launch.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
												{
													@Override
													public boolean onMenuItemClick(MenuItem m) {
														MUtil.launchApp(context, appInfo.pname());
														return true;
													}
												});
											MenuItem delete = menu.getMenu().add(0, mid++, 0, context.getString(R.string.delete));
											delete.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
												{
													@Override
													public boolean onMenuItemClick(MenuItem m) {
														MUtil.deleteApp(context, appInfo.pname());
														return true;
													}
												});
											menu.show();
										}
									});
							}
						});
					dialog.show();
					progress.cancel();
				}
			};
			new Handler().postDelayed(checkApk, 100);
		} else {
			installPKG(context, apk);
		}
	}

	public static void installPKG(Context c, File apk) {
		Uri data;
		if (Build.VERSION.SDK_INT >= 24) {
			Uri.Builder builder = new Uri.Builder();
			builder.authority(c.getPackageName() + ".fileprovider");
			builder.scheme("content");
			byte[] buf = apk.getAbsolutePath().getBytes();
			builder.path(Base64.encodeToString(buf, Base64.NO_WRAP));
			data = builder.build();
		} else
			data = Uri.fromFile(apk);
		Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
		intent.setFlags(3);
		intent.setData(data);
		c.startActivity(intent);
	}

	public static void openFile(Context c, File f) {
		try {
			Uri uri;
			String mime;
			Intent intent = new Intent(Intent.ACTION_VIEW);
			if (Build.VERSION.SDK_INT >= 24) {
				uri = FileProvider.getUriForFile(c, c.getPackageName() + ".outprovider", f);
				mime = c.getContentResolver().getType(uri);
				intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
			} else {
				uri = Uri.fromFile(f);
				mime = getMimeType(uri.toString());
			}
			intent.setDataAndType(uri, mime);
			c.startActivity(intent);
		} catch (Exception e) {
			TextUtil.st(c, String.format(c.getString(R.string.failed_open), f.getName()));
		}
	}

	public static String fileDigest(String file, String md) {
		String digest = null;
		try {
			InputStream fis =  new FileInputStream(file);
			byte[] buffer = new byte[2048];
			MessageDigest crypt = MessageDigest.getInstance(md);
			int count = 0;
			while ((count = fis.read(buffer)) != -1) {
				crypt.update(buffer, 0, count);
			}
			digest = TextUtil.byteToHex(crypt.digest());
			fis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return digest.toLowerCase();
	}

	public static long fileCRC32(String file) {
		long digest = 0;
		try {
			InputStream fis =  new FileInputStream(file);
			byte[] buffer = new byte[2048];
			Checksum checksum = new CRC32();
			int count = 0;
			while ((count = fis.read(buffer)) != -1) {
				checksum.update(buffer, 0, count);
			}
			digest = checksum.getValue();
			fis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return digest;
	}

	public static String getMimeType(String url) {
		String ext = MimeTypeMap.getFileExtensionFromUrl(url);
		String mime = null;
		if (ext != null) {
			mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
		}
		return mime;
	}

	public static String[] getStorages(Context context) {
		StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
		Class<?> storageVolumeClazz = null;
		try {
			storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
			Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
			Method getPath = storageVolumeClazz.getMethod("getPath");
			Object result = getVolumeList.invoke(mStorageManager);
			final int length = Array.getLength(result);
			String[] storages = new String[length];
			for (int i = 0; i < length; i++) {
				Object storageVolumeElement = Array.get(result, i);
				storages[i] = (String) getPath.invoke(storageVolumeElement);
			}
			return storages;
		} catch (Exception e) {
			return null;
		}
	}

	public static long getFileSize(File file) {
		long size = 0;
		if (file.isDirectory()) {
			File[] list = file.listFiles();
			if (list == null) {
				return size;
			}
			for (File child : list) {    
				size += getFileSize(child);
			}
		} else {
			size = file.length();
		}
		return size;
	}

	public static String humanReadableByteCount(long bytes, boolean si) {
		int unit = si ? 1000 : 1024;
		if (bytes < unit)
			return bytes + " B";
		int exp = (int) (Math.log(bytes) / Math.log(unit));
		String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
		return String.format("%.2f %sB", bytes / Math.pow(unit, exp), pre);
	}

	public static int countOfFiles(Context context, File targetDir, final boolean isDirectory) throws Exception {
		return countOfFiles(context, targetDir, isDirectory, false);
	}

	public static int countOfFiles(Context context, File targetDir, final boolean isDirectory, boolean recursive) throws Exception {
		if (targetDir == null || !targetDir.exists() || !targetDir.isDirectory()) {
			throw new Exception();
		}
		File[] temp = targetDir.listFiles(new FilenameFilter() {
				@Override
				public boolean accept(File file, String p2) {
					return Settings.hiddenFiles ? true : p2.charAt(0) != '.';
				}
			});
		int countFiles = 0;
		if (temp == null) {
			return countFiles;
		}
		for (File file : temp) {
			if (file.isDirectory() == isDirectory) {
				countFiles++;
			}
			if (file.isDirectory() && recursive) {
				countFiles += countOfFiles(context, file, isDirectory, recursive);
			}
		}
		return countFiles;
	}

	public static boolean copyFiles(File file1, File file2) {
		InputStream in = null;
		OutputStream out = null;
		try {
			in = new FileInputStream(file1);        
			out = new FileOutputStream(file2);
			byte[] buffer = new byte[1024];
			int read;
			while ((read = in.read(buffer)) != -1) {
				out.write(buffer, 0, read);
			}
			in.close();
			in = null;
            out.flush();
			out.close();
			out = null;
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (Exception e) {
			return false;
		}
	}

	public static boolean isInstalledApk(Context ctx, File file) {
		if (file == null)
			return false;
		return isInstalledApk(ctx, file.getAbsolutePath());
	}

	public static boolean isInstalledApk(Context ctx, String file) {
		String[] storages = getStorages(ctx.getApplicationContext());
		if (storages == null)
			return false;
		for (int i = 0; i < storages.length; i++) {
			if (file.startsWith(storages[i]))
				return false;
		}
		return true;
	}

	public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
		try {
			packageManager.getPackageInfo(packageName, 0);
			return true;
		} catch (PackageManager.NameNotFoundException e) {
			return false;
		}
	}

	public static HashSet<Integer> signaturesByName(Context ctx, String pname) {
		try {
			PackageInfo info = ctx.getPackageManager().getPackageInfo(pname, 0);
			return signaturesByPath(ctx, info.applicationInfo.sourceDir);
		} catch (PackageManager.NameNotFoundException e) {
			return new HashSet<Integer>();
		}
	}

	public static HashSet<Integer> signaturesByPath(Context ctx, String path) {
		HashSet<Integer> signatureSet = new HashSet<Integer>();   
		try {
			Signature[] signatures = ctx.getPackageManager().getPackageArchiveInfo(path, PackageManager.GET_SIGNATURES).signatures;
			for (Signature signature : signatures) {
				signatureSet.add(signature.hashCode());
			}
		} catch (Exception e) {}
		return signatureSet;
	}

	public static String[] packageInstalledInfo(Context ctx, PackageInfo pkg, PackageManager packageManager) {
		try {
			HashSet<Integer> signatures = signaturesByName(ctx, pkg.packageName);
			HashSet<Integer> signatures2 = signaturesByPath(ctx, pkg.applicationInfo.sourceDir);
			PackageInfo info = packageManager.getPackageInfo(pkg.packageName, PackageManager.GET_SIGNATURES);
			String match = ctx.getString(R.string.matches);
			if (!signatures.containsAll(signatures2)) {
				match = ctx.getString(R.string.not_match);
			}
			return new String[]{info.versionName + "(" + info.versionCode + ")", match};
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static boolean fileExists(Context context, String filename) {    
		File file = context.getFileStreamPath(filename);
		if (file == null || !file.exists()) {
			return false;
		}
		return true;
	}

	public static String genName(Context ctx, String path, String name, String suff, int cnt) {
		boolean overwrite = Settings.getb(ctx, "overwrite_apk", true);
		if (overwrite) {
			return name + suff;
		} else {
			try {
				String tn = name;
				if (cnt > 0) {
					tn = name + " (" + cnt + ")";
				}
				File check = new File(path + File.separator + tn + suff);
				if (check.exists()) {
					return genName(ctx, path, name, suff, ++cnt);
				} else {
					return tn + suff;
				}
			} catch (Exception e) {
				e.printStackTrace();
				return name + suff;
			}
		}
	}

	public static String genNameApk(Context ctx, String path, String name, String suff, int cnt) {
		String[] param = parseNameApk(name, suff);
		boolean overwrite = Settings.getb(ctx, "overwrite_apk", true);
		if (overwrite) {
			return param[0] + "." + param[1];
		} else {
			try {
				String tn = param[0];
				if (cnt > 0) {
					tn = param[0] + " (" + cnt + ")";
				}
				File check = new File(path + File.separator + tn + "." + param[1]);
				if (check.exists()) {
					return genNameApk(ctx, path, name, suff, ++cnt);
				} else {
					return tn + "." + param[1];
				}
			} catch (Exception e) {
				e.printStackTrace();
				return param[0] + "." + param[1];
			}
		}
	}

	public static boolean isText(File f) {
		final String[] textExt = new String[]{"txt", "xml", "conf", "prop", "cpp", "h", "java", "log", "json", "js", "php", "css", "py", "c", "smali", "cfg", "ini", "bat", "mf", "mtd", "lua", "htm", "html"};
		for (String ext : textExt) {
			if (f.getName().toLowerCase().endsWith("." + ext))
				return true;
		}
		Uri uri = Uri.fromFile(f);
		String mime = getMimeType(uri.toString());
		return (mime != null && mime.startsWith("text/"));
	}

	public static String[] parseFileName(String name) {
		if (name == null)
			return new String[]{"", ""};
		String filename = name;
		String extension = "";
		int i = name.lastIndexOf('.');
		if (i > 0) {
			filename = name.substring(0, i);
			extension = name.substring(i + 1);
			if (extension.indexOf(File.separator) >= 0) {
				filename = name;
				extension = "";
			}
		}
		return new String[]{filename, extension};
	}

	public static String[] parseNameApk(String name, String suff) {
		String filename = "out";
		String extension = "apk";

		int i = name.lastIndexOf('.');
		if (i > 0 && name != null) {
			filename = name.substring(0, i) + suff;
			extension = name.substring(i + 1);
		}
		return new String[]{filename, extension};
	}

	public static void unzip(Context ctx, Refreshable refresh, File zipFile, File targetDirectory) {
		new UnzipTask(ctx, refresh, targetDirectory).execute(zipFile);
	}

	public static boolean cpdir(File src, File dest) throws Exception {
		return FileUtils.cpdir(src, dest, false);
	}

	public static boolean cpdir(File src, File dest, boolean replace) throws Exception {
        dest.mkdirs();
        File[] files = src.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
			if (file.equals(dest))
				continue;
            File destFile = new File(dest.getPath() + File.separatorChar + file.getName());
            if (file.isDirectory()) {
                cpdir(file, destFile, replace);
                continue;
            }
			if (destFile.exists() && !replace)
				continue;
            try {
                InputStream in = new FileInputStream(file);
                OutputStream out = new FileOutputStream(destFile);
                IOUtils.copy(in, out);
                in.close();
                out.close();
            } catch (IOException ex) {
                throw new Exception("Could not copy file: " + file, ex);
            }
        }
		return true;
    }

	public static void quickEdit(final Context context, final File apk, final Refreshable refresh) {
		final Apkinfo appInfo = new Apkinfo(context, apk);
		if (!appInfo.isValid()) {
			TextUtil.st(context, context.getString(R.string.failed_open, apk.getName()));
			return;
		}
		final String dir;
		if (!apk.getParentFile().canWrite()) {
			dir = Settings.output_directory;
			if (dir == null) {
				TextUtil.st(context, context.getString(R.string.output_directory_not_set));
				return;
			}
			File d =  new File(dir);
			if (!d.exists() && !d.mkdirs()) {
				TextUtil.st(context, context.getString(R.string.output_directory_not_extsts, dir));
				return;
			}
			if (!d.isDirectory()) {
				TextUtil.st(context, context.getString(R.string.not_directory, dir));
				return;
			}
		} else {
			dir = apk.getParent();
		}
		final String appIcPath = (appInfo.iconValue() == null ? "" : appInfo.iconValue().split(":")[1]);
		final Bitmap[] bmp = new Bitmap[1];
		bmp[0] = null;
		final int maxSdk = Math.max(29, appInfo.targetSdk());
		final LayoutInflater inflater = LayoutInflater.from(context);
		final View view = inflater.inflate(R.layout.edit_dialog, null);
		final LinearLayout iconLayout = view.findViewById(R.id.editdialogLinearLayout1);
		if (appInfo.icon() == null) {
			iconLayout.setVisibility(LinearLayout.GONE);
		} else {
			final TextView tv = view.findViewById(R.id.editdialogTextView1);
			tv.setText("@" + appIcPath);
			final ImageView icon = view.findViewById(R.id.editdialogImageView1);
			View.OnClickListener click = new OnClickListener()
			{
				@Override
				public void onClick(View p1) {
					final FilePicker picker = new FilePicker(context);
					Runnable cback = new Runnable()
					{
						@Override
						public void run() {
							BitmapFactory.Options option = new BitmapFactory.Options();
							option.inPreferredConfig = Bitmap.Config.ARGB_8888;
							bmp[0] = BitmapFactory.decodeFile(picker.getPath(), option);
							BitmapDrawable draw = new BitmapDrawable(context.getResources(), bmp[0]);
							icon.setBackgroundDrawable(draw);
							tv.setText(picker.getPath());
						}
					};
					picker.setCallback(cback);
					picker.setFilter(new String[]{"gif", "png", "jpg", "jpeg", "bmp", "webp"});
					AlertDialog.Builder pbuilder = new AlertDialog.Builder(context);
					pbuilder.setTitle(R.string.mselect);
					pbuilder.setView(picker);
					pbuilder.setPositiveButton(R.string.cancel, null);
					pbuilder.setNeutralButton("/...", null);
					final AlertDialog dialog = pbuilder.create();
					dialog.setOnShowListener(new DialogInterface.OnShowListener() {
							@Override
							public void onShow(DialogInterface dialogInterface) {
								Button button = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
								button.setOnClickListener(new View.OnClickListener() {
										@Override
										public void onClick(View v) {
											String[] storages = getStorages(context);
											if (storages == null)
												return;
											PopupMenu menu = new PopupMenu(context, v);
											for (int i = 0; i < storages.length; i++) {
												MenuItem mi = menu.getMenu().add(0, (1100 + i), 0, storages[i]);
												mi.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
													{
														@Override
														public boolean onMenuItemClick(MenuItem m) {
															File root = new File(m.getTitle().toString());
															picker.refresh(root);
															return true;
														}
													});
											}
											menu.show();
										}
									});
							}
						});
					picker.setDialog(dialog);
					dialog.show();
				}
			};
			icon.setOnLongClickListener(new OnLongClickListener()
				{
					@Override
					public boolean onLongClick(View p1) {
						String icName = genName(context, dir, appIcPath.split("/")[1], ".png", 0);
						Bitmap iconbm = IconGenerate.drawableToBitmap(appInfo.icon());
						File r = IconGenerate.savebitmap(iconbm, new File(dir, icName));
						TextUtil.st(context, context.getString(R.string.extraction, r.getAbsolutePath()));
						refresh.refresh();
						return true;
					}
				});
			icon.setOnClickListener(click);
			tv.setOnClickListener(click);
			icon.setBackgroundDrawable(appInfo.icon());
		}
		final EditText label = view.findViewById(R.id.editdialogEditText1);
		label.setHint(appInfo.label());
		label.setText(appInfo.label());
		final EditText pname = view.findViewById(R.id.editdialogEditText2);
		pname.setHint(appInfo.pname());
		pname.setText(appInfo.pname());
		final EditText version = view.findViewById(R.id.editdialogEditText3);
		version.setHint(appInfo.version());
		version.setText(appInfo.version());
		final EditText build = view.findViewById(R.id.editdialogEditText4);
		build.setHint(appInfo.code() + "");
		build.setText(appInfo.code() + "");
		String[] sdkArray = new String[maxSdk];
		for (int i = 0; i < maxSdk; i++) {
			sdkArray[i] = (maxSdk - i) + " (" + MUtil.getSDK(maxSdk - i) + ")";
		}
		ArrayAdapter<String> sdkAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_dropdown_item, sdkArray);
		final Spinner minSdk = view.findViewById(R.id.editdialogSpinner1);
		minSdk.setAdapter(sdkAdapter);
		if (appInfo.minSdk() > 0)
			minSdk.setSelection(maxSdk - appInfo.minSdk());
		else
			minSdk.setEnabled(false);
		final Spinner targetSdk = view.findViewById(R.id.editdialogSpinner2);
		targetSdk.setAdapter(sdkAdapter);
		if (appInfo.targetSdk() > 0)
			targetSdk.setSelection(maxSdk - appInfo.targetSdk());
		else
			targetSdk.setEnabled(false);

		final CheckBox rmSplit = view.findViewById(R.id.editdialogCheckBox1);
		if (!appInfo.isSplitRequired()) {
			rmSplit.setVisibility(View.GONE);
		}
		AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setTitle(R.string.mapp_quickedit);
		builder.setView(view);
		builder.setPositiveButton(R.string.save, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface p1, int p2) {
					File temp = new File(dir + File.separator + ".A_TempQE_" + System.currentTimeMillis());
					if (!temp.mkdir()) {
						TextUtil.st(context, context.getString(R.string.error));
						return;
					}
					String newLabel = label.getText().toString();
					if (newLabel.equals(appInfo.label()))
						newLabel = null;
					String newPname = pname.getText().toString();
					if (newPname.equals(appInfo.pname()))
						newPname = null;
					String newVersion = version.getText().toString();
					if (newVersion.equals(appInfo.version()))
						newVersion = null;
					int newBuild = Integer.parseInt(build.getText().toString());
					if (newBuild == appInfo.code() || newBuild < 0)
						newBuild = 0;
					int min = maxSdk - minSdk.getSelectedItemPosition();
					if (min == appInfo.minSdk())
						min = 0;
					int target = maxSdk - targetSdk.getSelectedItemPosition();
					if (target == appInfo.targetSdk())
						target = 0;
					String newFile = TextUtil.replaceIllegal((newLabel == null ? appInfo.label() : newLabel) + "_v" + (newVersion == null ? appInfo.version() : newVersion) + "(" + (newBuild == 0 ? appInfo.code() : newBuild) + ")");
					QuickEdit editTask = new QuickEdit(context, refresh);
					editTask.setLabel(newLabel);
					editTask.setPname(newPname);
					editTask.setOriginalPname(appInfo.pname());
					editTask.setVersion(newVersion);
					editTask.setCode(newBuild);
					editTask.setMinSdk(min);
					editTask.setTargetSdk(target);
					editTask.removeSplit(rmSplit.isChecked());
					editTask.setBitmap(bmp[0]);
					editTask.setIconName(appIcPath);
					editTask.execute(apk.getAbsolutePath(), temp.getAbsolutePath() + File.separator + newFile + ".apk");
					p1.dismiss();
				}
			});
		builder.setNegativeButton(R.string.cancel, null);
		builder.setNeutralButton(R.string.minfo, null);
		final TextView info = view.findViewById(R.id.editdialogTextView2);
		final AlertDialog dialog = builder.create();
		dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
		dialog.setOnShowListener(new DialogInterface.OnShowListener() {
				@Override
				public void onShow(DialogInterface dialogInterface) {
					label.requestFocus();
					label.selectAll();
					Button button = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
					button.setOnClickListener(new View.OnClickListener() {
							@Override
							public void onClick(View v) {
								if (info.getVisibility() == View.GONE) {
									info.setVisibility(View.VISIBLE);
								} else {
									info.setVisibility(View.GONE);
								}
							}
						});
				}
			});
		dialog.show();
	}
}
